{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "635d8ebb",
   "metadata": {},
   "source": [
    "# Bind Tools\n",
    "\n",
    "- Author: [Jaemin Hong](https://github.com/geminii01)\n",
    "- Peer Review: [Hye-yoon Jeong](https://github.com/Hye-yoonJeong), [JoonHo Kim](https://github.com/jhboyo)\n",
    "- Proofread : [Chaeyoon Kim](https://github.com/chaeyoonyunakim)\n",
    "- This is a part of [LangChain Open Tutorial](https://github.com/LangChain-OpenTutorial/LangChain-OpenTutorial)\n",
    "\n",
    "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/LangChain-OpenTutorial/LangChain-OpenTutorial/blob/main/15-Agent/02-Bind-Tools.ipynb)[![Open in GitHub](https://img.shields.io/badge/Open%20in%20GitHub-181717?style=flat-square&logo=github&logoColor=white)](https://github.com/LangChain-OpenTutorial/LangChain-OpenTutorial/blob/main/15-Agent/02-Bind-Tools.ipynb)\n",
    "## Overview\n",
    "\n",
    "```bind_tools``` is a powerful function in LangChain for integrating custom tools with LLMs, enabling enriched AI workflows.\n",
    "\n",
    "This tutorial will show you how to create, bind tools, parse and execute outputs, and integrate them into an ```AgentExecutor``` .\n",
    "\n",
    "### Table of Contents\n",
    "\n",
    "- [Overview](#overview)\n",
    "- [Environment Setup](#environment-setup)\n",
    "- [Creating Tools](#creating-tools)\n",
    "- [Binding Tools](#binding-tools)\n",
    "- [Binding tools with Parser to Execute](#binding-tools-with-parser-to-execute)\n",
    "- [Binding tools with Agent and AgentExecutor](#binding-tools-with-agent-and-agentexecutor)\n",
    "\n",
    "### References\n",
    "\n",
    "- [Conceptual guide - Tool calling](https://python.langchain.com/docs/concepts/tool_calling/)\n",
    "- [tool_calls](https://python.langchain.com/docs/concepts/tool_calling/#tool-calling-1)\n",
    "- [AgentExecutor](https://python.langchain.com/api_reference/langchain/agents/langchain.agents.agent.AgentExecutor.html#langchain.agents.agent.AgentExecutor)\n",
    "----"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6c7aba4",
   "metadata": {},
   "source": [
    "## Environment Setup\n",
    "\n",
    "Set up the environment. You may refer to [Environment Setup](https://wikidocs.net/257836) for more details.\n",
    "\n",
    "**[Note]**\n",
    "- ```langchain-opentutorial``` is a package that provides a set of easy-to-use environment setup, useful functions and utilities for tutorials. \n",
    "- You can checkout the [```langchain-opentutorial```](https://github.com/LangChain-OpenTutorial/langchain-opentutorial-pypi) for more details."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "21943adb",
   "metadata": {},
   "outputs": [],
   "source": [
    "%%capture --no-stderr\n",
    "%pip install langchain-opentutorial"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f25ec196",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Install required packages\n",
    "from langchain_opentutorial import package\n",
    "\n",
    "package.install(\n",
    "    [\n",
    "        \"langsmith\",\n",
    "        \"langchain_community\",\n",
    "        \"langchain_core\",\n",
    "        \"langchain_openai\",\n",
    "    ],\n",
    "    verbose=False,\n",
    "    upgrade=False,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "7f9065ea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Environment variables have been set successfully.\n"
     ]
    }
   ],
   "source": [
    "# Set environment variables\n",
    "from langchain_opentutorial import set_env\n",
    "\n",
    "set_env(\n",
    "    {\n",
    "        \"OPENAI_API_KEY\": \"\",\n",
    "        \"LANGCHAIN_API_KEY\": \"\",\n",
    "        \"LANGCHAIN_TRACING_V2\": \"true\",\n",
    "        \"LANGCHAIN_ENDPOINT\": \"https://api.smith.langchain.com\",\n",
    "        \"LANGCHAIN_PROJECT\": \"02-Bind-Tools\",\n",
    "    }\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "690a9ae0",
   "metadata": {},
   "source": [
    "You can alternatively set API keys such as ```OPENAI_API_KEY``` in a ```.env``` file and load them.\n",
    "\n",
    "[Note] This is not necessary if you've already set the required API keys in previous steps."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "4f99b5b6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Load API keys from .env file\n",
    "from dotenv import load_dotenv\n",
    "\n",
    "load_dotenv(override=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16ba3a79",
   "metadata": {},
   "source": [
    "## Creating Tools\n",
    "\n",
    "Let's define tools for experimentation:\n",
    "\n",
    "- ```get_word_length``` : Returns the length of a word.\n",
    "- ```add_function``` : Adds two numbers.\n",
    "- ```bbc_news_crawl``` : Crawls BBC news and extracts main content.\n",
    "\n",
    "[Note]\n",
    "\n",
    "- Use the ```@tool``` decorator for defining tools, and provide clear docstrings."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "6b566815",
   "metadata": {},
   "outputs": [],
   "source": [
    "import requests\n",
    "from bs4 import BeautifulSoup\n",
    "from langchain_core.tools import tool\n",
    "\n",
    "\n",
    "# Define the tools\n",
    "@tool\n",
    "def get_word_length(word: str) -> int:\n",
    "    \"\"\"Return the length of the given text\"\"\"\n",
    "    return len(word)\n",
    "\n",
    "\n",
    "@tool\n",
    "def add_function(a: float, b: float) -> float:\n",
    "    \"\"\"Add two numbers together\"\"\"\n",
    "    return a + b\n",
    "\n",
    "\n",
    "@tool\n",
    "def bbc_news_crawl(news_url: str) -> str:\n",
    "    \"\"\"Crawl a news article from BBC\"\"\"\n",
    "    response = requests.get(news_url)\n",
    "    if response.status_code == 200:\n",
    "        soup = BeautifulSoup(response.text, \"html.parser\")\n",
    "\n",
    "        # Extract the desired information from the article\n",
    "        article = soup.find(\"article\")\n",
    "        if article:\n",
    "            title = article.find(\"h1\").get_text()  # Extract the title\n",
    "            content_list = [\n",
    "                tag.get_text()\n",
    "                for tag in article.find_all([\"h2\", \"p\"])\n",
    "                if (tag.name == \"h2\" and \"sc-518485e5-0\" in tag.get(\"class\", []))\n",
    "                or (tag.name == \"p\" and \"sc-eb7bd5f6-0\" in tag.get(\"class\", []))\n",
    "            ]  # Extract the content\n",
    "            content = \"\\n\\n\".join(content_list)\n",
    "    else:\n",
    "        print(f\"HTTP request failed. Response code: {response.status_code}\")\n",
    "    return f\"{title}\\n\\n----------\\n\\n{content}\"\n",
    "\n",
    "\n",
    "tools = [get_word_length, add_function, bbc_news_crawl]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab3458fd",
   "metadata": {},
   "source": [
    "## Binding Tools\n",
    "\n",
    "Now, let's use the ```bind_tools``` function to associate the defined tools with a specific LLM."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "1acc4c12",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "# Create a model\n",
    "llm = ChatOpenAI(model=\"gpt-4o\", temperature=0)\n",
    "\n",
    "# Tool binding\n",
    "llm_with_tools = llm.bind_tools(tools)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "16b07981",
   "metadata": {},
   "source": [
    "Let's check the results!\n",
    "\n",
    "The results are stored in ```tool_calls``` . Let's print ```tool_calls``` .\n",
    "\n",
    "[Note]\n",
    "\n",
    "- ```name``` indicates the name of the tool.\n",
    "- ```args``` contains the arguments that were passed to the tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "89015c42",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'name': 'get_word_length',\n",
       "  'args': {'word': 'LangChain OpenTutorial'},\n",
       "  'id': 'call_km7ieeNgjOvbPEfPt3bwO4cy',\n",
       "  'type': 'tool_call'}]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Execution result\n",
    "llm_with_tools.invoke(\n",
    "    \"What is the length of the given text 'LangChain OpenTutorial'?\"\n",
    ").tool_calls"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d8f42be",
   "metadata": {},
   "source": [
    "Next, we will connect ```llm_with_tools``` with ```JsonOutputToolsParser``` to parse ```tool_calls``` and review the results.\n",
    "\n",
    "[Note]\n",
    "\n",
    "- ```type``` indicates the type of the tool.\n",
    "- ```args``` contains the arguments that were passed to the tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "5453f7a5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'args': {'word': 'LangChain OpenTutorial'}, 'type': 'get_word_length'}]\n"
     ]
    }
   ],
   "source": [
    "from langchain_core.output_parsers.openai_tools import JsonOutputToolsParser\n",
    "\n",
    "# Tool Binding + Tool Parser\n",
    "chain = llm_with_tools | JsonOutputToolsParser(tools=tools)\n",
    "\n",
    "# Execution Result\n",
    "tool_call_results = chain.invoke(\n",
    "    \"What is the length of the given text 'LangChain OpenTutorial'?\"\n",
    ")\n",
    "print(tool_call_results)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "97ba29ef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[{'args': {'word': 'LangChain OpenTutorial'}, 'type': 'get_word_length'}]\n",
      "\n",
      "==========\n",
      "\n",
      "get_word_length\n",
      "{'word': 'LangChain OpenTutorial'}\n"
     ]
    }
   ],
   "source": [
    "print(tool_call_results)\n",
    "print(\"\\n==========\\n\")\n",
    "\n",
    "# First tool call result\n",
    "single_result = tool_call_results[0]\n",
    "\n",
    "print(single_result[\"type\"])\n",
    "print(single_result[\"args\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ef1b5fc",
   "metadata": {},
   "source": [
    "Execute the corresponding tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "049d605f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "('get_word_length', 'get_word_length')"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "tool_call_results[0][\"type\"], tools[0].name"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c4797141",
   "metadata": {},
   "source": [
    "The ```execute_tool_calls``` function identifies the appropriate tool, passes the corresponding ```args``` , and then executes the tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "9267052a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Executed Tool] get_word_length [Args] {'word': 'LangChain OpenTutorial'}\n",
      "[Execution Result] 22\n"
     ]
    }
   ],
   "source": [
    "def execute_tool_calls(tool_call_results):\n",
    "    \"\"\"\n",
    "    Function to execute the tool call results.\n",
    "\n",
    "    :param tool_call_results: List of the tool call results\n",
    "    :param tools: List of available tools\n",
    "    \"\"\"\n",
    "\n",
    "    # Iterate over the list of the tool call results\n",
    "    for tool_call_result in tool_call_results:\n",
    "        # Tool name (function name)\n",
    "        tool_name = tool_call_result[\"type\"]\n",
    "        # Tool arguments\n",
    "        tool_args = tool_call_result[\"args\"]\n",
    "\n",
    "        # Find the tool that matches the name and execute it\n",
    "        # Use the next() function to find the first matching tool\n",
    "        matching_tool = next((tool for tool in tools if tool.name == tool_name), None)\n",
    "        if matching_tool:\n",
    "            # Execute the tool\n",
    "            result = matching_tool.invoke(tool_args)\n",
    "            print(\n",
    "                f\"[Executed Tool] {tool_name} [Args] {tool_args}\\n[Execution Result] {result}\"\n",
    "            )\n",
    "        else:\n",
    "            print(f\"Warning: Unable to find the tool corresponding to {tool_name}.\")\n",
    "\n",
    "\n",
    "# Execute the tool calls\n",
    "execute_tool_calls(tool_call_results)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcaa07a5",
   "metadata": {},
   "source": [
    "## Binding tools with Parser to Execute\n",
    "\n",
    "This time, we will combine the entire process of binding tools, parsing the results, and executing the tool calls into a single step.\n",
    "\n",
    "- ```llm_with_tools``` : The LLM model with bound tools.\n",
    "- ```JsonOutputToolsParser``` : The parser that processes the results of tool calls.\n",
    "- ```execute_tool_calls``` : The function that executes the results of tool calls.\n",
    "\n",
    "[Flow Summary]\n",
    "\n",
    "1. Bind tools to the model.\n",
    "2. Parse the results of tool calls.\n",
    "3. Execute the results of tool calls."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "19f1708b",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.output_parsers.openai_tools import JsonOutputToolsParser\n",
    "\n",
    "# bind_tools + Parser + Execution\n",
    "chain = llm_with_tools | JsonOutputToolsParser(tools=tools) | execute_tool_calls"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "68095403",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Executed Tool] get_word_length [Args] {'word': 'LangChain OpenTutorial'}\n",
      "[Execution Result] 22\n"
     ]
    }
   ],
   "source": [
    "# Execution Result 1\n",
    "chain.invoke(\"What is the length of the given text 'LangChain OpenTutorial'?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "d74e69f5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Executed Tool] add_function [Args] {'a': 114.5, 'b': 121.2}\n",
      "[Execution Result] 235.7\n",
      "235.7\n"
     ]
    }
   ],
   "source": [
    "# Execution Result 2\n",
    "chain.invoke(\"114.5 + 121.2\")\n",
    "\n",
    "# Double check\n",
    "print(114.5 + 121.2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "3cf368a3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[Executed Tool] bbc_news_crawl [Args] {'news_url': 'https://www.bbc.com/news/articles/cew52g8p2lko'}\n",
      "[Execution Result] New AI hub 'to create 1,000 jobs' on Merseyside\n",
      "\n",
      "----------\n",
      "\n",
      "A new Artificial Intelligence (AI) hub planned for Merseyside is set to create 1,000 jobs over the next three years, the government said.\n",
      "\n",
      "Prime Minister Sir Keir Starmer said he wanted to make the UK one of the world's AI \"super powers\" as a way of boosting economic growth and improving public services.\n",
      "\n",
      "Global IT company Kyndryl announced it was going to create the new tech hub in the Liverpool City Region.\n",
      "\n",
      "Metro Mayor Steve Rotheram welcomed the investment, saying it would be \"hugely beneficial\" to the area.\n",
      "\n",
      "'International investment'\n",
      "\n",
      "In a speech setting out the government's AI ambitions, Starmer spoke of its \"vast potential\" for rejuvenating public services.\n",
      "\n",
      "The government said its AI Opportunities Action Plan was backed by leading tech firms, some of which have committed £14bn towards various projects including growth zones, creating 13,250 jobs.\n",
      "\n",
      "Mr Rotheram told BBC Radio Merseyside: \"I went over last year to speak to [Kyndryl] face-to-face in New York.\n",
      "\n",
      "\"To have that come to fruition so quickly is hugely beneficial to the workforce in the Liverpool City Region.\" \n",
      "\n",
      "He said attracting the world's largest IT infrastructure services provider was \"testament to what we can achieve when local ambition is matched by national support to help attract international investment\".\n",
      "\n",
      "The Labour mayor said the Liverpool City Region was \"leading the way in the UK's AI revolution\". \n",
      "\n",
      "He added: \"As a region with a proud history of innovation we're ready to seize the opportunities that AI and digital technology can bring; not just to boost our economy but to improve lives, develop skills, tackle inequality, and ensure no-one is left behind.\"\n",
      "\n",
      "The BBC has asked the Department for Science, Innovation and Technology for more details about Merseyside's AI hub plans.\n",
      "\n",
      "Listen to the best of BBC Radio Merseyside on Sounds and follow BBC Merseyside on Facebook, X, and Instagram and watch BBC North West Tonight on BBC iPlayer.\n"
     ]
    }
   ],
   "source": [
    "# Execution Result 3\n",
    "chain.invoke(\"Crawl the news article: https://www.bbc.com/news/articles/cew52g8p2lko\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c3ba409e",
   "metadata": {},
   "source": [
    "## Binding tools with Agent and ```AgentExecutor```\n",
    "\n",
    "```bind_tools``` provides schemas (tools) that can be used by the model.\n",
    "\n",
    "```AgentExecutor``` creates an execution loop for tasks such as invoking the LLM, routing to the appropriate tool, executing it, and re-invoking the model.\n",
    "\n",
    "[Note]\n",
    "\n",
    "- Agent and ```AgentExecutor``` will be covered in detail in the *next chapter* ."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "4b881d35",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "# Create an Agent prompt\n",
    "prompt = ChatPromptTemplate.from_messages(\n",
    "    [\n",
    "        (\n",
    "            \"system\",\n",
    "            \"You are very powerful assistant, but don't know current events\",\n",
    "        ),\n",
    "        (\"user\", \"{input}\"),\n",
    "        MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n",
    "    ]\n",
    ")\n",
    "\n",
    "# Create a model\n",
    "llm = ChatOpenAI(model=\"gpt-4o\", temperature=0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "3d104a01",
   "metadata": {},
   "outputs": [],
   "source": [
    "from langchain.agents import AgentExecutor, create_tool_calling_agent\n",
    "\n",
    "# Use the tools defined previously\n",
    "tools = [get_word_length, add_function, bbc_news_crawl]\n",
    "\n",
    "# Create an Agent\n",
    "agent = create_tool_calling_agent(llm, tools, prompt)\n",
    "\n",
    "# Create an AgentExecutor\n",
    "agent_executor = AgentExecutor(\n",
    "    agent=agent,\n",
    "    tools=tools,\n",
    "    verbose=True,\n",
    "    handle_parsing_errors=True,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e252d7d",
   "metadata": {},
   "source": [
    "Let's calculate the length of a word."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "d1f0f576",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `get_word_length` with `{'word': 'LangChain OpenTutorial'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[36;1m\u001b[1;3m22\u001b[0m\u001b[32;1m\u001b[1;3mThe length of the text \"LangChain OpenTutorial\" is 22 characters.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "The length of the text \"LangChain OpenTutorial\" is 22 characters.\n"
     ]
    }
   ],
   "source": [
    "# Execute the Agent\n",
    "result = agent_executor.invoke(\n",
    "    {\"input\": \"What is the length of the given text 'LangChain OpenTutorial'?\"}\n",
    ")\n",
    "\n",
    "# Execution Result\n",
    "print(result[\"output\"])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bf69114",
   "metadata": {},
   "source": [
    "Let's calculate the sum of two numbers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "c5af5f33",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `add_function` with `{'a': 114.5, 'b': 121.2}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m235.7\u001b[0m\u001b[32;1m\u001b[1;3mThe result of 114.5 + 121.2 is 235.7.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "The result of 114.5 + 121.2 is 235.7.\n",
      "\n",
      "==========\n",
      "\n",
      "235.7\n"
     ]
    }
   ],
   "source": [
    "# Execute the Agent\n",
    "result = agent_executor.invoke({\"input\": \"Calculate the result of 114.5 + 121.2\"})\n",
    "\n",
    "# Execution Result\n",
    "print(result[\"output\"])\n",
    "print(\"\\n==========\\n\")\n",
    "print(114.5 + 121.2)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7932ae8",
   "metadata": {},
   "source": [
    "Let's add more than two numbers. \n",
    "\n",
    "In this scenario, you can observe that the agent is capable of verifying its own intermediate results and repeating the process if necessary to arrive at the correct final answer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "b6f585aa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `add_function` with `{'a': 114.5, 'b': 121.2}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m235.7\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `add_function` with `{'a': 235.7, 'b': 34.2}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m269.9\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `add_function` with `{'a': 34.2, 'b': 110.1}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m144.3\u001b[0m\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `add_function` with `{'a': 269.9, 'b': 110.1}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3m380.0\u001b[0m\u001b[32;1m\u001b[1;3mThe result of adding 114.5, 121.2, 34.2, and 110.1 is 380.0.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "The result of adding 114.5, 121.2, 34.2, and 110.1 is 380.0.\n",
      "\n",
      "==========\n",
      "\n",
      "380.0\n"
     ]
    }
   ],
   "source": [
    "# Execute the Agent\n",
    "result = agent_executor.invoke(\n",
    "    {\"input\": \"Calculate the result of 114.5 + 121.2 + 34.2 + 110.1\"}\n",
    ")\n",
    "\n",
    "# Execution Result\n",
    "print(result[\"output\"])\n",
    "print(\"\\n==========\\n\")\n",
    "print(114.5 + 121.2 + 34.2 + 110.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1794961e",
   "metadata": {},
   "source": [
    "Finally, let's try using a tool to summarize a news article."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "730455ab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `bbc_news_crawl` with `{'news_url': 'https://www.bbc.com/news/articles/cew52g8p2lko'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[38;5;200m\u001b[1;3mNew AI hub 'to create 1,000 jobs' on Merseyside\n",
      "\n",
      "----------\n",
      "\n",
      "A new Artificial Intelligence (AI) hub planned for Merseyside is set to create 1,000 jobs over the next three years, the government said.\n",
      "\n",
      "Prime Minister Sir Keir Starmer said he wanted to make the UK one of the world's AI \"super powers\" as a way of boosting economic growth and improving public services.\n",
      "\n",
      "Global IT company Kyndryl announced it was going to create the new tech hub in the Liverpool City Region.\n",
      "\n",
      "Metro Mayor Steve Rotheram welcomed the investment, saying it would be \"hugely beneficial\" to the area.\n",
      "\n",
      "'International investment'\n",
      "\n",
      "In a speech setting out the government's AI ambitions, Starmer spoke of its \"vast potential\" for rejuvenating public services.\n",
      "\n",
      "The government said its AI Opportunities Action Plan was backed by leading tech firms, some of which have committed £14bn towards various projects including growth zones, creating 13,250 jobs.\n",
      "\n",
      "Mr Rotheram told BBC Radio Merseyside: \"I went over last year to speak to [Kyndryl] face-to-face in New York.\n",
      "\n",
      "\"To have that come to fruition so quickly is hugely beneficial to the workforce in the Liverpool City Region.\" \n",
      "\n",
      "He said attracting the world's largest IT infrastructure services provider was \"testament to what we can achieve when local ambition is matched by national support to help attract international investment\".\n",
      "\n",
      "The Labour mayor said the Liverpool City Region was \"leading the way in the UK's AI revolution\". \n",
      "\n",
      "He added: \"As a region with a proud history of innovation we're ready to seize the opportunities that AI and digital technology can bring; not just to boost our economy but to improve lives, develop skills, tackle inequality, and ensure no-one is left behind.\"\n",
      "\n",
      "The BBC has asked the Department for Science, Innovation and Technology for more details about Merseyside's AI hub plans.\n",
      "\n",
      "Listen to the best of BBC Radio Merseyside on Sounds and follow BBC Merseyside on Facebook, X, and Instagram and watch BBC North West Tonight on BBC iPlayer.\u001b[0m\u001b[32;1m\u001b[1;3mA new Artificial Intelligence (AI) hub is planned for Merseyside, expected to create 1,000 jobs over the next three years. Prime Minister Sir Keir Starmer aims to position the UK as a global AI \"superpower\" to boost economic growth and improve public services. The global IT company Kyndryl will establish the tech hub in the Liverpool City Region. Metro Mayor Steve Rotheram praised the investment, highlighting its benefits for the area. The government's AI Opportunities Action Plan, supported by leading tech firms, has secured £14 billion for various projects, including growth zones, creating 13,250 jobs. Rotheram emphasized the region's leadership in the UK's AI revolution and its readiness to leverage AI and digital technology for economic and social benefits.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n",
      "A new Artificial Intelligence (AI) hub is planned for Merseyside, expected to create 1,000 jobs over the next three years. Prime Minister Sir Keir Starmer aims to position the UK as a global AI \"superpower\" to boost economic growth and improve public services. The global IT company Kyndryl will establish the tech hub in the Liverpool City Region. Metro Mayor Steve Rotheram praised the investment, highlighting its benefits for the area. The government's AI Opportunities Action Plan, supported by leading tech firms, has secured £14 billion for various projects, including growth zones, creating 13,250 jobs. Rotheram emphasized the region's leadership in the UK's AI revolution and its readiness to leverage AI and digital technology for economic and social benefits.\n"
     ]
    }
   ],
   "source": [
    "# Execute the Agent\n",
    "result = agent_executor.invoke(\n",
    "    {\n",
    "        \"input\": \"Summarize the news article: https://www.bbc.com/news/articles/cew52g8p2lko\"\n",
    "    }\n",
    ")\n",
    "\n",
    "# Execution Result\n",
    "print(result[\"output\"])"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "langchain-kr-lwwSZlnu-py3.11",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
